package com.py.framework.core.interceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.py.framework.core.annotation.IgnoreAuthority;
import com.py.framework.core.common.SpringContextHolder;
import com.py.framework.core.common.URLConstants;
import com.py.framework.core.helper.HttpServletHelper;
import com.py.framework.core.helper.UrlHelper;
import com.py.framework.core.http.HttpAgent;
import com.py.framework.core.log.ExceptionLogger;
import com.py.framework.core.rest.support.RestServiceResult;
import com.py.framework.core.utils.FileUtils;

public class SignInterceptor extends HandlerInterceptorAdapter {

	/** 令牌名称 **/
	public static final String Token = "Token";

	/** 资源请求头 **/
	public static final String JD_RESOURCE = "JD-Resource";

	/** 白名单列表 **/
	private List<String> whiteUrls;

	private int _size = 0;

	/** 鉴权服务地址 **/
	private String checkAuthUrl;

	/** 信用评价前台网站令牌名称 **/
	public static final String XYPJ_GATEWAY_TOKEN = "XYPJ-Gateway-Token";

	/** 信用评价前台网站配置url **/
	private List<String> gatewayUrls;

	public SignInterceptor() {

		String path = SignInterceptor.class.getResource("/").getFile();
		whiteUrls = FileUtils.readFile(path + "white/signWhite.txt");
		_size = null == whiteUrls ? 0 : whiteUrls.size();

		this.gatewayUrls = FileUtils.readFile(path + "gateway/gatewayUrl.txt");
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		HandlerMethod method = (HandlerMethod) handler;

		IgnoreAuthority methodAnnotation = method.getMethodAnnotation(IgnoreAuthority.class);

		if (methodAnnotation != null) {
			return true;
		}

		String servletPath = request.getServletPath();

		if (StringUtils.isBlank(servletPath)) {
			String reqUri = request.getRequestURI();
			String ctxPath = request.getContextPath();
			servletPath = reqUri.replaceFirst(ctxPath, "");
		}

		// 判断请求名称是否是信用评价前台网站接口(信用评价前台网站接口url不能与后台其他接口url重复)
		if (null != this.gatewayUrls && this.isGatewayAccess(servletPath)) {

			return isGatewayFilter(request, response, servletPath);
			// 信用评价前台网站接口拦截

		} else {

			return isBackgroundFilter(request, response, servletPath);
			// 其他后台接口拦截

		}
	}

	/**
	 * 输出文本
	 * 
	 * @param response
	 * @param code
	 * @param msg
	 * @throws IOException
	 */
	private void printMsg(HttpServletResponse response, int code, String msg) throws IOException {
		// 设置格式为text/json
		response.setContentType("text/json");
		// 设置字符集为'UTF-8'
		response.setCharacterEncoding("UTF-8");

		// 设置返回信息
		RestServiceResult<String> result = new RestServiceResult<String>();
		result.setCode(code);
		result.setMsg(msg);

		PrintWriter out = response.getWriter();
		out.println(JSON.toJSONString(result));
		out.flush();
		out.close();
	}

	/**
	 * 后台功能模块拦截过滤
	 * 
	 * @param request
	 * @param response
	 * @param servletPath
	 * @return
	 * @throws IOException
	 * @throws ServletException
	 */
	private boolean isBackgroundFilter(HttpServletRequest request, HttpServletResponse response, String servletPath)
			throws IOException, ServletException {

		// 白名单之外的请求都要鉴权
		if (!isWhiteRequest(servletPath, _size, whiteUrls)) {
			/*
			 * 首先从cookie中查找令牌, 如果不存在, 再从请求头中查找.
			 */
			String jdToken = HttpServletHelper.getUserToken(request);
			// Token是否为空
			if (StringUtils.isBlank(jdToken)) {
				// 输出响应信息
				this.printMsg(response, RestServiceResult.CODE_LOGOUT, "此用户未登录2！");
				return false;
			}
			// 鉴权地址是否为空
			if (StringUtils.isBlank(this.checkAuthUrl)) {
				UrlHelper urlHelper = SpringContextHolder.getBean(UrlHelper.class);
				if (null != urlHelper && StringUtils.isNotBlank(urlHelper.getBaseServerUrl())) {
					this.checkAuthUrl = urlHelper.getBaseServerUrl() + URLConstants.CHECK_RESOURCE_URL;
				} else {
					// 输出响应信息
					this.printMsg(response, RestServiceResult.CODE_UNKNOW, "鉴权服务地址为空！");
					return false;
				}
			}
			// 设置请求头信息
			Map<String, String> headers = new HashMap<>();
			headers.put(Token, jdToken);
			headers.put(JD_RESOURCE, servletPath);
			// 验证是否为有效用户
			try {
				// String result =
				// HttpAgent.getInstance().sendHttpPost(this.checkAuthUrl,
				// jdToken);
				String result = HttpAgent.getInstance().sendHttpPost(this.checkAuthUrl, "resource=" + servletPath,
						headers);
				if (StringUtils.isNotBlank(result)) {
					RestServiceResult<String> json = JSON.parseObject(result,
							new TypeReference<RestServiceResult<String>>() {
							});
					if (null != json) {
						if (json.getCode() == RestServiceResult.CODE_LOGOUT) {
							// 输出响应信息
							this.printMsg(response, RestServiceResult.CODE_LOGOUT, "此用户未登录3！");
							return false;
						} else if (json.getCode() == RestServiceResult.CODE_NOAUTH) {
							// 输出响应信息
							this.printMsg(response, RestServiceResult.CODE_NOAUTH, "此用户无权限！");
							return false;
						} else if (json.getCode() == RestServiceResult.CODE_UNKNOW) {
							// 输出响应信息
							this.printMsg(response, RestServiceResult.CODE_UNKNOW, "失败！");
							return false;
						}
					} else {
						// 输出响应信息
						this.printMsg(response, RestServiceResult.CODE_UNKNOW, "失败！");
						return false;
					}
				} else {
					// 输出响应信息
					this.printMsg(response, RestServiceResult.CODE_UNKNOW, "失败！");
					return false;
				}
			} catch (Exception e) {
				ExceptionLogger.error(e);
				// 输出响应信息
				this.printMsg(response, RestServiceResult.CODE_UNKNOW, "失败！");
				return false;
			}

		}

		return true;
	}

	/**
	 * 前台信用评价网站拦截过滤
	 * 
	 * @return
	 */
	private boolean isGatewayFilter(HttpServletRequest request, HttpServletResponse response, String servletPath)
			throws IOException, ServletException {
		/*
		 * 首先从cookie中查找令牌, 如果不存在, 再从请求头中查找.
		 */
		String xypjGatewayToken = HttpServletHelper.getUserXypjGatewayToken(request);
		// Token是否为空
		if (StringUtils.isBlank(xypjGatewayToken)) {
			// 输出响应信息
			this.printMsg(response, RestServiceResult.CODE_LOGOUT, "此用户未登录4！");
			return false;
		}

		// 设置请求头信息
		Map<String, String> headers = new HashMap<>();
		headers.put(XYPJ_GATEWAY_TOKEN, xypjGatewayToken);

		return true;
	}

	/** 判断是否是白名单 */
	public boolean isWhiteRequest(String url, int size, List<String> whiteUrls) {
		if (url == null || "".equals(url) || size == 0) {
			return true;
		} else {
			url = url.toLowerCase();
			for (String urlTemp : whiteUrls) {
				if (url.indexOf(urlTemp.toLowerCase()) > -1) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 判断资源是否是信用评价前台网站
	 * @param resource 资源地址
	 * @return
	 */
	private boolean isGatewayAccess(String resource) {
		boolean flag = false;
		if (this.gatewayUrls.contains(resource)) {
			flag = true;
		} else {
			for (String key:this.gatewayUrls
					) {
				if (key.endsWith("/*")) {
					key = key.substring(0, (key.length() - 1));
					if (resource.startsWith(key)) {
						flag = true;
						break;
					}
				}
			}
		}
		return flag;
	}
}
